#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Maven安装器GUI工具
功能：
1. 自动检测操作系统
2. 获取Maven版本列表
3. 提供GUI界面选择版本和安装目录
4. 自动下载和安装Maven
5. 支持深色/浅色主题
6. 安装历史记录
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import platform
import requests
import json
import os
import subprocess
import threading
import zipfile
import tarfile
from pathlib import Path
import shutil
import warnings
from datetime import datetime
import time

# 忽略SSL警告
warnings.filterwarnings('ignore', message='urllib3 v2 only supports OpenSSL 1.1.1+')


class MavenInstallerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("Maven安装器")
        self.root.geometry("650x600")
        self.root.resizable(True, True)
        
        # 设置样式
        self.style = ttk.Style()
        self.style.theme_use('clam')
        
        # 变量
        self.os_info = self.detect_os()
        self.maven_versions = []
        self.selected_version = tk.StringVar()
        self.install_path = tk.StringVar()
        self.download_progress = tk.DoubleVar()
        self.dark_mode = tk.BooleanVar(value=False)
        
        # 历史记录
        self.history_file = os.path.join(os.path.expanduser("~"), ".maven_installer_history.json")
        self.installation_history = self.load_history()
        
        # 设置界面
        self.setup_ui()
        self.apply_theme()
        self.load_maven_versions()
    
    def detect_os(self):
        """检测操作系统信息"""
        system = platform.system().lower()
        machine = platform.machine().lower()
        
        os_info = {
            'system': system,
            'machine': machine,
            'platform': platform.platform(),
            'version': platform.version()
        }
        
        # 确定下载文件扩展名
        if system == 'windows':
            os_info['extension'] = 'zip'
            os_info['binary_name'] = 'mvn.cmd'
        elif system == 'darwin':  # macOS
            os_info['extension'] = 'tar.gz'
            os_info['binary_name'] = 'mvn'
        else:  # Linux
            os_info['extension'] = 'tar.gz'
            os_info['binary_name'] = 'mvn'
        
        return os_info
    
    def setup_ui(self):
        """设置用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        
        # 创建标签页
        notebook = ttk.Notebook(main_frame)
        notebook.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        main_frame.rowconfigure(0, weight=1)
        
        # 安装页面
        install_frame = ttk.Frame(notebook, padding="10")
        notebook.add(install_frame, text="安装Maven")
        
        # 历史记录页面
        history_frame = ttk.Frame(notebook, padding="10")
        notebook.add(history_frame, text="安装历史")
        
        # 设置页面
        settings_frame = ttk.Frame(notebook, padding="10")
        notebook.add(settings_frame, text="设置")
        
        # 设置各个页面
        self.setup_install_page(install_frame)
        self.setup_history_page(history_frame)
        self.setup_settings_page(settings_frame)
    
    def setup_install_page(self, parent):
        """设置安装页面"""
        # 操作系统信息
        os_frame = ttk.LabelFrame(parent, text="操作系统信息", padding="10")
        os_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        os_frame.columnconfigure(1, weight=1)
        
        ttk.Label(os_frame, text="操作系统:").grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
        ttk.Label(os_frame, text=self.os_info['platform']).grid(row=0, column=1, sticky=tk.W)
        
        ttk.Label(os_frame, text="架构:").grid(row=1, column=0, sticky=tk.W, padx=(0, 10))
        ttk.Label(os_frame, text=self.os_info['machine']).grid(row=1, column=1, sticky=tk.W)
        
        # Maven版本选择
        version_frame = ttk.LabelFrame(parent, text="Maven版本选择", padding="10")
        version_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        version_frame.columnconfigure(1, weight=1)
        
        ttk.Label(version_frame, text="选择版本:").grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
        self.version_combo = ttk.Combobox(version_frame, textvariable=self.selected_version, state="readonly")
        self.version_combo.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 10))
        
        refresh_btn = ttk.Button(version_frame, text="刷新版本", command=self.load_maven_versions)
        refresh_btn.grid(row=0, column=2)
        
        # 安装目录选择
        install_frame = ttk.LabelFrame(parent, text="安装目录", padding="10")
        install_frame.grid(row=2, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        install_frame.columnconfigure(1, weight=1)
        
        ttk.Label(install_frame, text="安装路径:").grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
        install_entry = ttk.Entry(install_frame, textvariable=self.install_path)
        install_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 10))
        
        browse_btn = ttk.Button(install_frame, text="浏览", command=self.browse_directory)
        browse_btn.grid(row=0, column=2)
        
        # 设置默认安装路径
        default_path = self.get_default_install_path()
        self.install_path.set(default_path)
        
        # 进度条
        progress_frame = ttk.LabelFrame(parent, text="安装进度", padding="10")
        progress_frame.grid(row=3, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        progress_frame.columnconfigure(0, weight=1)
        
        self.progress_bar = ttk.Progressbar(progress_frame, variable=self.download_progress, maximum=100)
        self.progress_bar.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 10))
        
        self.progress_label = ttk.Label(progress_frame, text="准备就绪")
        self.progress_label.grid(row=0, column=1)
        
        # 日志区域
        log_frame = ttk.LabelFrame(parent, text="安装日志", padding="10")
        log_frame.grid(row=4, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
        parent.rowconfigure(4, weight=1)
        
        self.log_text = tk.Text(log_frame, height=8, wrap=tk.WORD)
        scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=scrollbar.set)
        
        self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        # 按钮
        button_frame = ttk.Frame(parent)
        button_frame.grid(row=5, column=0, pady=(10, 0))
        
        self.install_btn = ttk.Button(button_frame, text="开始安装", command=self.start_installation)
        self.install_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        self.cancel_btn = ttk.Button(button_frame, text="取消", command=self.cancel_installation, state="disabled")
        self.cancel_btn.pack(side=tk.LEFT)
        
        # 安装状态
        self.installing = False
    
    def setup_history_page(self, parent):
        """设置历史记录页面"""
        # 创建Treeview显示历史记录
        columns = ('时间', '版本', '路径', '状态')
        self.history_tree = ttk.Treeview(parent, columns=columns, show='headings')
        
        for col in columns:
            self.history_tree.heading(col, text=col)
            self.history_tree.column(col, width=100)
        
        self.history_tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        scrollbar = ttk.Scrollbar(parent, orient=tk.VERTICAL, command=self.history_tree.yview)
        self.history_tree.configure(yscrollcommand=scrollbar.set)
        scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)
        
        # 更新历史记录显示
        self.update_history_display()
        
        # 按钮
        button_frame = ttk.Frame(parent)
        button_frame.grid(row=1, column=0, columnspan=2, pady=(10, 0))
        
        clear_btn = ttk.Button(button_frame, text="清空历史", command=self.clear_history)
        clear_btn.pack(side=tk.LEFT, padx=(0, 10))
    
    def setup_settings_page(self, parent):
        """设置设置页面"""
        # 主题设置
        theme_frame = ttk.LabelFrame(parent, text="主题设置", padding="10")
        theme_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        
        theme_switch = ttk.Checkbutton(theme_frame, text="深色模式", variable=self.dark_mode,
                                      command=self.apply_theme)
        theme_switch.grid(row=0, column=0, sticky=tk.W)
        
        # 关于信息
        about_frame = ttk.LabelFrame(parent, text="关于", padding="10")
        about_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        about_frame.columnconfigure(0, weight=1)
        
        about_text = """Maven安装器

版本: 1.0.0
作者: AI助手
描述: 一个用于自动安装Maven的图形界面工具

功能:
- 自动检测操作系统
- 获取Maven版本列表
- 自动下载和安装Maven
- 安装历史记录
- 主题切换
"""
        
        about_label = ttk.Label(about_frame, text=about_text, justify=tk.LEFT)
        about_label.grid(row=0, column=0, sticky=tk.W)
        
        parent.columnconfigure(0, weight=1)
    
    def apply_theme(self):
        """应用主题"""
        if self.dark_mode.get():
            # 深色主题
            self.style.configure('TFrame', background='#2c3e50')
            self.style.configure('TLabel', background='#2c3e50', foreground='#ecf0f1')
            self.style.configure('TLabelframe', background='#2c3e50', foreground='#ecf0f1')
            self.style.configure('TLabelframe.Label', background='#2c3e50', foreground='#ecf0f1')
            self.style.configure('TButton', background='#3498db', foreground='#ecf0f1')
            self.style.configure('TCheckbutton', background='#2c3e50', foreground='#ecf0f1')
            self.style.configure('TCombobox', background='#34495e', foreground='#ecf0f1')
            self.style.configure('TEntry', background='#34495e', foreground='#ecf0f1')
            self.style.configure('TProgressbar', background='#3498db')
            self.style.configure('Treeview', background='#34495e', foreground='#ecf0f1', fieldbackground='#34495e')
            self.style.configure('Treeview.Heading', background='#2c3e50', foreground='#ecf0f1')
            
            self.log_text.config(bg='#34495e', fg='#ecf0f1')
            self.root.configure(bg='#2c3e50')
        else:
            # 浅色主题
            self.style.theme_use('clam')
            self.log_text.config(bg='white', fg='black')
            self.root.configure(bg=self.style.lookup('TFrame', 'background'))
    
    def get_default_install_path(self):
        """获取默认安装路径"""
        if self.os_info['system'] == 'windows':
            return os.path.join(os.environ.get('PROGRAMFILES', 'C:\\Program Files'), 'Maven')
        elif self.os_info['system'] == 'darwin':  # macOS
            return '/usr/local/maven'
        else:  # Linux
            return '/opt/maven'
    
    def browse_directory(self):
        """浏览选择安装目录"""
        directory = filedialog.askdirectory(title="选择Maven安装目录")
        if directory:
            self.install_path.set(directory)
    
    def log_message(self, message):
        """添加日志消息"""
        timestamp = datetime.now().strftime('%H:%M:%S')
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()
    
    def load_maven_versions(self):
        """加载Maven版本列表"""
        def fetch_versions():
            try:
                self.log_message("正在获取Maven版本列表...")
                
                # 使用Maven官方API获取版本列表
                url = "https://repo1.maven.org/maven2/org/apache/maven/apache-maven/maven-metadata.xml"
                response = requests.get(url, timeout=10)
                
                if response.status_code == 200:
                    # 解析XML获取版本信息
                    import xml.etree.ElementTree as ET
                    root = ET.fromstring(response.text)
                    
                    versions = []
                    for version in root.findall('.//version'):
                        if version.text and not version.text.endswith('-SNAPSHOT'):
                            versions.append(version.text)
                    
                    # 按版本号排序（降序）
                    def version_key(version):
                        try:
                            # 处理版本号，只取数字部分进行排序
                            parts = version.split('.')
                            key_parts = []
                            for part in parts:
                                # 提取数字部分
                                num_part = ''
                                for char in part:
                                    if char.isdigit():
                                        num_part += char
                                    else:
                                        break
                                key_parts.append(int(num_part) if num_part else 0)
                            return key_parts
                        except:
                            return [0]  # 如果解析失败，放在最前面
                    
                    versions.sort(key=version_key, reverse=True)
                    
                    self.maven_versions = versions[:20]  # 只显示最新的20个版本
                    
                    # 更新UI
                    self.root.after(0, self.update_version_combo)
                    self.root.after(0, lambda: self.log_message(f"成功获取到 {len(self.maven_versions)} 个Maven版本"))
                    
                else:
                    self.root.after(0, lambda: self.log_message(f"获取版本列表失败: HTTP {response.status_code}"))
                    
            except Exception as e:
                self.root.after(0, lambda: self.log_message(f"获取版本列表时出错: {str(e)}"))
        
        # 在后台线程中获取版本
        threading.Thread(target=fetch_versions, daemon=True).start()
    
    def update_version_combo(self):
        """更新版本下拉框"""
        self.version_combo['values'] = self.maven_versions
        if self.maven_versions:
            self.selected_version.set(self.maven_versions[0])  # 默认选择最新版本
    
    def start_installation(self):
        """开始安装"""
        if not self.selected_version.get():
            messagebox.showerror("错误", "请选择一个Maven版本")
            return
        
        if not self.install_path.get():
            messagebox.showerror("错误", "请选择安装目录")
            return
        
        # 确认安装
        result = messagebox.askyesno(
            "确认安装",
            f"确定要安装Maven {self.selected_version.get()} 到 {self.install_path.get()} 吗？"
        )
        
        if result:
            self.installing = True
            self.install_btn.config(state="disabled")
            self.cancel_btn.config(state="normal")
            
            # 在后台线程中执行安装
            threading.Thread(target=self.install_maven, daemon=True).start()
    
    def cancel_installation(self):
        """取消安装"""
        self.installing = False
        self.install_btn.config(state="normal")
        self.cancel_btn.config(state="disabled")
        self.log_message("安装已取消")
    
    def install_maven(self):
        """安装Maven"""
        try:
            version = self.selected_version.get()
            install_dir = self.install_path.get()
            
            self.root.after(0, lambda: self.log_message(f"开始安装Maven {version}"))
            self.root.after(0, lambda: self.progress_label.config(text="准备下载..."))
            
            # 创建安装目录
            os.makedirs(install_dir, exist_ok=True)
            
            # 下载Maven
            download_url = self.get_download_url(version)
            self.root.after(0, lambda: self.log_message(f"下载URL: {download_url}"))
            
            # 下载文件
            filename = f"apache-maven-{version}-bin.{self.os_info['extension']}"
            filepath = os.path.join(install_dir, filename)
            
            self.download_file(download_url, filepath)
            
            if not self.installing:
                self.add_to_history(version, install_dir, "已取消")
                return
            
            self.root.after(0, lambda: self.log_message("下载完成，开始解压..."))
            self.root.after(0, lambda: self.progress_label.config(text="正在解压..."))
            
            # 解压文件
            self.extract_file(filepath, install_dir)
            
            if not self.installing:
                self.add_to_history(version, install_dir, "已取消")
                return
            
            # 移动文件到最终位置
            extracted_dir = os.path.join(install_dir, f"apache-maven-{version}")
            final_dir = os.path.join(install_dir, "maven")
            
            if os.path.exists(final_dir):
                shutil.rmtree(final_dir)
            shutil.move(extracted_dir, final_dir)
            
            # 清理下载文件
            os.remove(filepath)
            
            self.root.after(0, lambda: self.log_message("Maven安装完成！"))
            self.root.after(0, lambda: self.progress_label.config(text="安装完成"))
            self.root.after(0, lambda: self.download_progress.set(100))
            
            # 添加到历史记录
            self.add_to_history(version, final_dir, "成功")
            
            # 显示环境变量配置信息
            self.show_environment_setup(final_dir)
            
        except Exception as e:
            self.root.after(0, lambda: self.log_message(f"安装失败: {str(e)}"))
            self.root.after(0, lambda: self.progress_label.config(text="安装失败"))
            self.add_to_history(self.selected_version.get(), install_dir, f"失败: {str(e)}")
        finally:
            self.installing = False
            self.root.after(0, lambda: self.install_btn.config(state="normal"))
            self.root.after(0, lambda: self.cancel_btn.config(state="disabled"))
    
    def get_download_url(self, version):
        """获取下载URL"""
        base_url = "https://archive.apache.org/dist/maven/maven-3"
        filename = f"apache-maven-{version}-bin.{self.os_info['extension']}"
        return f"{base_url}/{version}/binaries/{filename}"
    
    def download_file(self, url, filepath):
        """下载文件"""
        response = requests.get(url, stream=True, timeout=30)
        response.raise_for_status()
        
        total_size = int(response.headers.get('content-length', 0))
        downloaded_size = 0
        start_time = time.time()
        
        with open(filepath, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                if not self.installing:
                    return
                
                f.write(chunk)
                downloaded_size += len(chunk)
                
                if total_size > 0:
                    progress = (downloaded_size / total_size) * 100
                    
                    # 计算下载速度
                    elapsed_time = time.time() - start_time
                    if elapsed_time > 0:
                        speed = downloaded_size / elapsed_time / 1024  # KB/s
                        
                        self.root.after(0, lambda p=progress: self.download_progress.set(p))
                        self.root.after(0, lambda d=downloaded_size, t=total_size, s=speed: 
                                      self.progress_label.config(text=f"下载中... {d//1024//1024}MB/{t//1024//1024}MB ({s:.1f} KB/s)"))
                    else:
                        self.root.after(0, lambda p=progress: self.download_progress.set(p))
                        self.root.after(0, lambda d=downloaded_size, t=total_size: 
                                      self.progress_label.config(text=f"下载中... {d//1024//1024}MB/{t//1024//1024}MB"))
    
    def extract_file(self, filepath, extract_dir):
        """解压文件"""
        if filepath.endswith('.zip'):
            with zipfile.ZipFile(filepath, 'r') as zip_ref:
                zip_ref.extractall(extract_dir)
        elif filepath.endswith('.tar.gz'):
            with tarfile.open(filepath, 'r:gz') as tar_ref:
                tar_ref.extractall(extract_dir)
    
    def show_environment_setup(self, maven_home):
        """显示环境变量配置信息"""
        bin_path = os.path.join(maven_home, "bin")
        
        env_info = f"""
Maven安装完成！

安装路径: {maven_home}

请手动配置环境变量：

Windows:
set MAVEN_HOME={maven_home}
set PATH=%PATH%;{bin_path}

macOS/Linux:
export MAVEN_HOME={maven_home}
export PATH=$PATH:{bin_path}

或者将以下内容添加到 ~/.bashrc 或 ~/.zshrc:
export MAVEN_HOME={maven_home}
export PATH=$PATH:{bin_path}

配置完成后，请重新打开终端并运行 'mvn --version' 验证安装。
"""
        
        # 创建新窗口显示环境变量信息
        env_window = tk.Toplevel(self.root)
        env_window.title("环境变量配置")
        env_window.geometry("600x400")
        
        text_widget = tk.Text(env_window, wrap=tk.WORD, padx=10, pady=10)
        text_widget.pack(fill=tk.BOTH, expand=True)
        text_widget.insert(tk.END, env_info)
        text_widget.config(state=tk.DISABLED)
        
        # 添加复制按钮
        copy_btn = ttk.Button(env_window, text="复制到剪贴板", 
                             command=lambda: self.copy_to_clipboard(env_info))
        copy_btn.pack(pady=10)
    
    def copy_to_clipboard(self, text):
        """复制文本到剪贴板"""
        self.root.clipboard_clear()
        self.root.clipboard_append(text)
        messagebox.showinfo("成功", "环境变量配置信息已复制到剪贴板")
    
    def load_history(self):
        """加载历史记录"""
        if os.path.exists(self.history_file):
            try:
                with open(self.history_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except:
                return []
        return []
    
    def save_history(self):
        """保存历史记录"""
        try:
            with open(self.history_file, 'w', encoding='utf-8') as f:
                json.dump(self.installation_history, f, ensure_ascii=False)
        except Exception as e:
            self.log_message(f"保存历史记录失败: {str(e)}")
    
    def add_to_history(self, version, install_path, status):
        """添加到历史记录"""
        history_item = {
            'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'version': version,
            'path': install_path,
            'status': status
        }
        
        self.installation_history.insert(0, history_item)  # 添加到开头
        
        # 限制历史记录数量
        if len(self.installation_history) > 50:
            self.installation_history = self.installation_history[:50]
        
        self.save_history()
        self.update_history_display()
    
    def update_history_display(self):
        """更新历史记录显示"""
        # 清空现有项目
        for item in self.history_tree.get_children():
            self.history_tree.delete(item)
        
        # 添加历史记录
        for item in self.installation_history:
            self.history_tree.insert('', 'end', values=(
                item.get('time', ''),
                item.get('version', ''),
                item.get('path', ''),
                item.get('status', '')
            ))
    
    def clear_history(self):
        """清空历史记录"""
        if messagebox.askyesno("确认", "确定要清空历史记录吗？"):
            self.installation_history = []
            self.save_history()
            self.update_history_display()
            self.log_message("历史记录已清空")


def main():
    root = tk.Tk()
    app = MavenInstallerGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()